/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.hwr.nbaplan.server.dataload;

import de.hwr.nbaplan.server.DbConnect;
import de.hwr.nbaplan.shared.model.Kurs;
import de.hwr.nbaplan.shared.model.Studiengang;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 *
 * @author flo
 */
public class Crawler {

    private static final int CRAWL_DAYS = 10;
    private List<Studiengang> studiengaenge;
    private EntityManagerFactory emf = Persistence.createEntityManagerFactory("NBA-PlanPU");

    /**
     *
     * @throws Exception
     */
    public Crawler() throws Exception {
        this.loadStudiengaenge();
        this.crawlKurse(studiengaenge);
        this.loadPlans();

    }

    private void loadStudiengaenge() throws Exception {
        List<Studiengang> temp = (List<Studiengang>) DbConnect.getEm().createNamedQuery("Studiengang.findAll").getResultList();
        if (temp == null) {
            throw new Exception("keine Studiengänge geladen");
        }
        this.studiengaenge = temp;

    }

    private void crawlKurse(List<Studiengang> studiengaenge) {
        for (Studiengang studeingang : studiengaenge) {
            if ((GregorianCalendar) studeingang.getLastCrowl() == null) {
                this.crawlKurse(studeingang);
            }
            int days = (int) ((new GregorianCalendar().getTimeInMillis() - (studeingang.getLastCrowl().getTimeInMillis())) / 86400000);
            if (CRAWL_DAYS < days) {
                this.crawlKurse(studeingang);
            }

        }
    }

    private void crawlKurse(Studiengang studiengang) {
        studiengang.setLastCrowl(new GregorianCalendar());

        List<Kurs> kurse = (List<Kurs>) studiengang.getKursCollection();
        String[] kursChars = {"", "a", "b", "c", "d"};
        for (int i = 1; i <= 6; i++) {
            for (String kursChar : kursChars) {
                try {
                    URL url = new URL(studiengang.getICSUrl(i, kursChar));
                    int responsecode = ((HttpURLConnection) url.openConnection()).getResponseCode();
                    if (responsecode != 404) {
                        Kurs tempKurs = exists(kurse, i, kursChar);
                        if (tempKurs == null) {
                            tempKurs = new Kurs(studiengang, i, kursChar);
                            studiengang.getKursCollection().add(tempKurs);
                            //persist(tempKurs);
                        }
                    }

                } catch (IOException ex) {
                    Logger.getLogger(Crawler.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        update(studiengang);
    }

    private void loadPlans() {
        for (Studiengang studeingang : studiengaenge) {
            loadPlans(studeingang);
        }
    }

    private void loadPlans(Studiengang studiengang) {
        for(Kurs kurs: studiengang.getKursCollection()){
             System.out.println(studiengang.getICSUrl(kurs));
            loadPlans(kurs);
        }
    }

    private void loadPlans(Kurs kurs) {
      
        ICSLoader loader = new ICSLoader(kurs);
        try {
            loader.parse(kurs);
        } catch (IOException ex) {
            Logger.getLogger(Crawler.class.getName()).log(Level.SEVERE, null, ex);
        }
       
    }

    private Kurs exists(List<Kurs> kurse, int sem, String kursChar) {
        for (Kurs kurs : kurse) {
            if (kurs.getSemester() == sem && kurs.getMyKursChar().equals(kursChar)) {
                return kurs;
            }
        }
        return null;
    }

    /**
     *
     * @param object
     */
    public void update(Object object) {
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.merge(object);
            em.getTransaction().commit();
        } catch (Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e);
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }

    /**
     *
     * @param object
     */
    public void persist(Object object) {
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(object);
            em.getTransaction().commit();
        } catch (Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e);
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }
}
